#include <stdio.h>
#include <stdlib.h>
#include"polynomials.h"

struct node_poly
{
    float coef;
    int exponent;
    ptrnode next;
};

ptr_list create_ptr(int length, float* coef_array, int* exp_array)
{
    printf("call createList\n");
    ptr_list ptr_head;
    ptrnode ptr_node;
    //l->next = NULL;
    // the head_node:
    ptr_node = (ptr_list) malloc(sizeof(node_poly));
    ptr_head = ptr_node;
    ptr_head -> next = NULL;   
    if(length >= 1) 
    {
        position p;
    // other node
        p = ptr_head;
        for (int i = 0; i < length; ++i)
        {
            printf("start \n");
            ptr_node = (ptr_list) malloc(sizeof(node_poly));
            ptr_node -> coef = coef_array[i];
            ptr_node -> exponent = exp_array[i];
            p -> next = ptr_node;
            p = ptr_node;
            printf("create %d\n", i);
        }
        p -> next = NULL;
    }
    return ptr_head;
}

ptr_list ptr_add(ptr_list ptr1, ptr_list ptr2)
{
    printf("call ptr_add\n");
    ptr_list ptr3;
    ptrnode ptr_node;
    position p1, p2, p3;
    
    ptr3 = create_ptr(0, NULL, NULL);

    p1 = ptr1->next;
    p2 = ptr2->next;
    p3 = ptr3;
    // both of them are not empty
    while(p1 && p2)
    {
        if(p1->exponent > p2->exponent)
        {
            ptr_node = (ptr_list) malloc(sizeof(node_poly));
            ptr_node -> coef = p1->coef;
            ptr_node -> exponent = p1->exponent;
            p3 -> next = ptr_node;
            p3 = ptr_node;
            p1 = p1->next;
        }
        else if(p1->exponent < p2->exponent)
        {
            ptr_node = (ptr_list) malloc(sizeof(node_poly));
            ptr_node -> coef = p2->coef;
            ptr_node -> exponent = p2->exponent;
            p3 -> next = ptr_node;
            p3 = ptr_node;
            p2 = p2->next;
        }
        // equal
        //need to add them
        else
        {
            ptr_node = (ptr_list) malloc(sizeof(node_poly));
            ptr_node -> coef = p2->coef + p1->coef;
            ptr_node -> exponent = p2->exponent;
            p3 -> next = ptr_node;
            p3 = ptr_node;
            p1 = p1->next;
            p2 = p2->next;
        }
    }
    //if p1 not end
    while(p1)
    {
        ptr_node = (ptr_list) malloc(sizeof(node_poly));
        ptr_node -> coef = p1->coef;
        ptr_node -> exponent = p1->exponent;
        p3 -> next = ptr_node;
        p3 = ptr_node;
        p1 = p1->next;
    }
    //if p2 not end
    while(p2)
    {
        ptr_node = (ptr_list) malloc(sizeof(node_poly));
        ptr_node -> coef = p2->coef;
        ptr_node -> exponent = p2->exponent;
        p3 -> next = ptr_node;
        p3 = ptr_node;
        p2 = p2->next;
    }
    p3 -> next = NULL;
    // one of them is empty
    return ptr3;
}

/*
ptr2 ptr1: ptr_list by descrease
*/
ptr_list ptr_multiply(ptr_list ptr1, ptr_list ptr2)
{
    printf("call ptr_multiply\n");
    ptr_list ptr3;
    ptrnode ptr_node;
    position p1, p2, p3;
    float p3_coef = 0;
    int exp_max, exponent_sum;
    
    //one of them is null
    if (ptr1->next == NULL || ptr2->next == NULL)
    {
        printf("one of the ptr is null\n");
        return NULL;
    }
        

    ptr3 = create_ptr(0, NULL, NULL);
    p1 = ptr1->next;
    p2 = ptr2->next;
    p3 = ptr3;
    exp_max = p1->exponent + p2->exponent;

    inverse_ptr(ptr2);
    printPtrList(ptr2);
        
    
    p2 = ptr2 ->next;
    for(int i = exp_max; i >= 0; i --)
    {
        p1 = ptr1->next;
        p2 = ptr2->next;
        p3_coef = 0;
        while(p1 && p2)
        {
            //equal
            exponent_sum = p1->exponent + p2->exponent;
            if (exponent_sum == i)
            {
                p3_coef = p1->coef * p2->coef;
                p1 = p1->next;
                p2 = p2->next;
            }
            else if (exponent_sum < i)
            {
                p2 = p2->next;
            }
            else
            {
                p1 = p1->next;
            }
        }
        if(p3_coef != 0.0 )
        {
           ptr_node = (ptr_list) malloc(sizeof(node_poly));
           ptr_node -> coef = p3_coef;
           ptr_node -> exponent = i;
           p3 -> next = ptr_node;
           p3 = ptr_node; 
        }
        
    }
    p3->next = NULL;
    return ptr3; 
}

void inverse_ptr(ptr_list ptr)
{
    position p1, p2, p3;
    if (ptr->next == NULL || (ptr -> next)->next == NULL)
        return;
    p1 = ptr->next;
    p2 = p1->next;
    p3 = p2->next;
    while(p3)
    {
        p2->next = p1;
        p1 = p2;
        p2 = p3;
        p3 = p3->next;
    }
    p2->next = p1;
    // don't forget
    (ptr->next)->next =NULL;
    ptr -> next = p2;

}

void printPtrList(ptr_list ptr)
{
    printf("Call printPtrList\n");
    position p;
    if (!isEmpty_ptr(ptr))
    {
        printf("PtrList is not empty\n");
        p = ptr ->next;
        while(p -> next)
        {
            printf("%f*x^", p -> coef);
            printf("%d + ", p -> exponent );
            p = p ->next;

        }
        printf("%f*x^", p -> coef);
        printf("%d", p-> exponent );
        printf("\n");
    }
    
}
bool isEmpty_ptr(ptr_list l)
{
    if(l ->next == NULL)
        return true;
    else
        return false;
}